import logging
import time

from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QLabel

from data.DataHandler import datahandler
from data.WarningClass import WarningClass
from data.defines import *
from data.warnning_config import warnhandler, WarnParamInfo
from gcs_views.TakeoffCheckListPad import TakeoffCheckListPad
from gcs_views.ui_gcs_gui_2 import *


def warn_status_check(readout_air_temp: QLabel, cur_warn_level: int):
    if cur_warn_level == WarnParamInfo.NORMAL:
        readout_air_temp.setStyleSheet('font: 12pt "Noto Sans S Chinese Bold";color: rgb(255, 255, 255);')
    elif cur_warn_level == WarnParamInfo.WARN:
        readout_air_temp.setStyleSheet('font: 12pt "Noto Sans S Chinese Bold";color: rgb(255, 255, 0);')
    else:
        readout_air_temp.setStyleSheet('font: 12pt "Noto Sans S Chinese Bold";color: rgb(255, 0, 0);')


def _upload_freq_invalid():
    """
    上行遥控数据帧频异常
    :return:
    """
    if warnhandler.Ulink_Freq.cur_warn_level == WarnParamInfo.CRITICAL \
            and warnhandler.Llink_Freq.cur_warn_level == WarnParamInfo.CRITICAL \
            and warnhandler.Glink_Freq.cur_warn_level == WarnParamInfo.CRITICAL:
        return True
    else:
        return False


def _download_freq_invalid():
    if warnhandler.Downlload_Freq.cur_warn_level == WarnParamInfo.CRITICAL:
        return True
    else:
        return False


def _engine_lube_temp_invalid():
    if datahandler.connect_status:
        if warnhandler.Eng_LubeTmp.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_lube_press_invalid():
    if datahandler.connect_status:
        if warnhandler.Eng_LubePress.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_fuel_press_invalid():
    if datahandler.connect_status:
        if warnhandler.Press_Fuel.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _fcc_disconnect():
    """
    有告警信息时进行告警
    :return:
    """
    return not datahandler.connect_status


def _engine_low_fuel():
    if datahandler.connect_status:
        if warnhandler.fuel_Left.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Fuel_right.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_airbox_temp():
    if datahandler.connect_status:
        if warnhandler.Press_Air.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_gen_temp_abnormal():
    if datahandler.connect_status:
        if warnhandler.Eng_Gene1.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Eng_Gene2.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_cyl_temp_abnormal():
    if datahandler.connect_status:
        if warnhandler.Eng_Cyl2Tmp.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Eng_Cyl3Tmp.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_gas_temp_abnormal():
    if datahandler.connect_status:
        if warnhandler.Temp_Gas1.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Temp_Gas2.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Temp_Gas3.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.Temp_Gas4.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _ele_servo_bias():
    if datahandler.connect_status:
        if warnhandler.ELER_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.ELEL_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _rud_servo_bias():
    if datahandler.connect_status:
        if warnhandler.RUD_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL:
            warnhandler.RUD_Actuator_Bias.counter += 1
            if warnhandler.RUD_Actuator_Bias.counter >= 5:
                return True
            else:
                return False
        else:
            warnhandler.RUD_Actuator_Bias.counter = 0
            return False
    else:
        return False


def _ail_servo_bias():
    if datahandler.connect_status:
        if warnhandler.AILL_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL \
                or warnhandler.AILR_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _flap_servo_bias():
    if datahandler.connect_status:
        if warnhandler.FLAP_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL:
            warnhandler.FLAP_Actuator_Bias.counter += 1
            if warnhandler.FLAP_Actuator_Bias.counter >= 10:
                return True
            else:
                return False
        else:
            warnhandler.FLAP_Actuator_Bias.counter = 0
            return False
    else:
        return False


def _front_grear_servo_bias():
    if datahandler.connect_status:
        if warnhandler.Gear_Actuator_Bias.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_cur_bat_abnormal():
    if datahandler.connect_status:
        if warnhandler.Cur_Bat.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_vol_A_abnormal():
    if datahandler.connect_status:
        if warnhandler.Vol_A.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_cur_A_abnormal():
    if datahandler.connect_status:
        if warnhandler.Cur_A.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_vol_B_abnormal():
    if datahandler.connect_status:
        if warnhandler.Cur_B.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_cur_B_abnormal():
    if datahandler.connect_status:
        if warnhandler.Vol_B.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    return False


def _elec_vol_C_abnormal():
    if datahandler.connect_status:
        if warnhandler.Vol_C.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _elec_cur_C_abnormal():
    if datahandler.connect_status:
        if warnhandler.Cur_C.cur_warn_level == WarnParamInfo.CRITICAL:
            return True
        else:
            return False
    else:
        return False


def _engine_fire_warnning():
    if datahandler.connect_status:
        if warnhandler.Eng_Cyl2Tmp.cur_val > warnhandler.Eng_Cyl2Tmp.limit4 \
                and warnhandler.Eng_Cyl3Tmp.cur_val > warnhandler.Eng_Cyl3Tmp.limit4 \
                and warnhandler.Eng_Gene1.cur_val > warnhandler.Eng_Gene1.limit4 \
                and warnhandler.Eng_Gene2.cur_val > warnhandler.Eng_Gene2.limit4:
            return True
        else:
            return False
    else:
        return False


class GCSMainClass(Ui_GCSWindow2):
    btn_enable_style_sheet \
        = 'background-color: rgb(0,255, 0,200);color: rgb(255, 255, 255);font: 12pt "Noto Sans S Chinese Bold";'
    btn_disable_style_sheet \
        = 'background-color: rgb(200, 200, 200, 200);color: rgb(255, 255, 255);font: 12pt "Noto Sans S Chinese Bold";'

    def __init__(self):
        super(GCSMainClass, self).__init__()
        self.adc_heat_status = 0
        self.adc_heat_status_mismach_counter = 0
        self.state_pos = 0
        self.ins_state = 0
        self.breakr_back_bar = 0.0
        self.breakr_percent = 0.0
        self.breakl_percent = 0.0
        self.breakl_back_bar = 0.0
        self.height_source = 0
        self.radar1_connect = 0
        self.radar2_connect = 0
        self.radar3_connect = 0
        self.fuel_left_l = 0.0
        self.fuel_right_l = 0.0
        self.trust_percent = 4.0
        self.trust_percent_back = 4.0
        self.eng_thr = 0.0
        self.eng_rpm = 0
        self.adc_connect = 0
        self.adc_freq = 0
        self.adc_ram_error = 0
        self.adc_mach_invalid = 0
        self.adc_hdot_invalid = 0
        self.adc_vi_invalid = 0
        self.adc_height_invalid = 0
        self.adc_total_press_invalid = 0
        self.adc_static_press_invalid = 0
        self.adc_normal = 0
        self.adc_height_m = 0
        self.adc_vi_mps = 0
        self.adc_mach = 0
        self.adc_hdot_mps = 0
        self.link_protect = 0
        self.altitude_source = 0
        self.attitude_source = 0
        self.navigation_source = 0

        self.timer5Hz = QTimer()  # 创建窗口定时器，用于处理周期任务
        self.timer5Hz.timeout.connect(self.timer_process_5Hz)
        self.timer5Hz.start(200)
        self.counter = 0
        self.remote_upload_on = 1  # 远程remote switch开启标识 1-代表开启上传，0-代表不开启
        self.takeoff_checklist_pad = TakeoffCheckListPad()

        self.warn_1 = WarningClass("数据链遥控链路异常", 3, InfoListWidget.CRITICAL, _upload_freq_invalid, self.warning_publish)
        self.warn_2 = WarningClass("数据链遥测链路异常", 3, InfoListWidget.CRITICAL, _download_freq_invalid,
                                   self.warning_publish)
        # self.warn_3 = WarningClass("数据链信号质量差", 3, InfoListWidget.WARNING, _fcc_disconnect, self.warning_publish)
        self.warn_4 = WarningClass("大气机气压高度异常", 3, InfoListWidget.WARNING, self._adc_height_invalid,
                                   self.warning_publish)
        self.warn_5 = WarningClass("大气机空速异常", 3, InfoListWidget.WARNING, self._adc_vi_invalid, self.warning_publish)
        self.warn_6 = WarningClass("大气机垂直速度异常", 3, InfoListWidget.WARNING, self._adc_hdot_invalid, self.warning_publish)
        # self.warn_7 = WarningClass("VHF工作异常", 3, InfoListWidget.WARNING, _fcc_disconnect, self.warning_publish)
        self.warn_8 = WarningClass("发动机转速异常", 3, InfoListWidget.WARNING, self._engine_over_speed, self.warning_publish)
        self.warn_9 = WarningClass("发动机油门开度异常", 3, InfoListWidget.WARNING, self._engine_thr_abnormal,
                                   self.warning_publish)
        self.warn_10 = WarningClass("滑油温度异常", 30, InfoListWidget.WARNING, _engine_lube_temp_invalid,
                                    self.warning_publish)
        self.warn_11 = WarningClass("滑油压力异常", 30, InfoListWidget.WARNING, _engine_lube_press_invalid,
                                    self.warning_publish)
        # self.warn_12 = WarningClass("燃油消耗率波动异常", 30, InfoListWidget.WARNING, _fcc_disconnect, self.warning_publish)
        self.warn_13 = WarningClass("燃油压力异常", 30, InfoListWidget.WARNING, _engine_fuel_press_invalid,
                                    self.warning_publish)
        self.warn_14 = WarningClass("燃油量告警", 30, InfoListWidget.CRITICAL, _engine_low_fuel, self.warning_publish)
        self.warn_15 = WarningClass("空气箱温度异常", 30, InfoListWidget.WARNING, _engine_airbox_temp, self.warning_publish)
        self.warn_16 = WarningClass("发电机温度异常", 30, InfoListWidget.WARNING, _engine_gen_temp_abnormal,
                                    self.warning_publish)
        self.warn_17 = WarningClass("气缸温度异常", 30, InfoListWidget.CRITICAL, _engine_cyl_temp_abnormal,
                                    self.warning_publish)
        self.warn_18 = WarningClass("排气温度异常", 30, InfoListWidget.WARNING, _engine_gas_temp_abnormal,
                                    self.warning_publish)
        self.warn_19 = WarningClass("雷达高度异常", 3, InfoListWidget.WARNING, self._radar_invalid, self.warning_publish)
        self.warn_20 = WarningClass("高度信号源故障", 3, InfoListWidget.WARNING, self._height_src_invalid,
                                    self.warning_publish)
        self.warn_21 = WarningClass("导航信号源故障", 3, InfoListWidget.WARNING, self._nav_src_invalid, self.warning_publish)
        self.warn_22 = WarningClass("姿态信号源故障", 3, InfoListWidget.CRITICAL, self._attitude_src_invalid,
                                    self.warning_publish)
        self.warn_23 = WarningClass("升降舵机故障", 3, InfoListWidget.CRITICAL, _ele_servo_bias, self.warning_publish)
        self.warn_24 = WarningClass("方向舵机故障", 3, InfoListWidget.CRITICAL, _rud_servo_bias, self.warning_publish)
        self.warn_25 = WarningClass("左/右副翼舵机故障", 3, InfoListWidget.CRITICAL, _ail_servo_bias, self.warning_publish)
        self.warn_26 = WarningClass("襟翼舵机故障", 3, InfoListWidget.WARNING, _flap_servo_bias, self.warning_publish)
        self.warn_27 = WarningClass("油门舵机故障", 3, InfoListWidget.CRITICAL, self._trust_servo_bias, self.warning_publish)
        self.warn_28 = WarningClass("前轮转向舵机故障", 3, InfoListWidget.CRITICAL, _front_grear_servo_bias,
                                    self.warning_publish)
        self.warn_29 = WarningClass("左/右刹车压力故障", 3, InfoListWidget.CRITICAL, self._brake_press_abnormal,
                                    self.warning_publish)
        # self.warn_30 = WarningClass("结冰探测器故障", 3, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        self.warn_31 = WarningClass("空速管加温故障", 30, InfoListWidget.CRITICAL, self._adc_heat_fail, self.warning_publish)
        # self.warn_32 = WarningClass("货舱火警", 30, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        self.warn_33 = WarningClass("发动机火警", 30, InfoListWidget.CRITICAL, _engine_fire_warnning, self.warning_publish)
        # self.warn_34 = WarningClass("货舱/发动机火情探测器故障", 30, InfoListWidget.CRITICAL, _fcc_disconnect,
        #                             self.warning_publish)
        # self.warn_35 = WarningClass("发动机模式错误", 30, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        # self.warn_36 = WarningClass("横向模式错误", 30, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        # self.warn_37 = WarningClass("纵向模式错误", 30, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        # self.warn_38 = WarningClass("惯导状态错误", 30, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)
        self.warn_39 = WarningClass("14V电流异常", 60, InfoListWidget.WARNING, _elec_vol_C_abnormal, self.warning_publish)
        self.warn_40 = WarningClass("14V电压异常", 60, InfoListWidget.WARNING, _elec_cur_C_abnormal, self.warning_publish)
        self.warn_41 = WarningClass("汇流条A电流异常", 60, InfoListWidget.WARNING, _elec_cur_A_abnormal, self.warning_publish)
        self.warn_42 = WarningClass("汇流条A电压异常", 60, InfoListWidget.WARNING, _elec_vol_A_abnormal, self.warning_publish)
        self.warn_43 = WarningClass("汇流条B电流异常", 60, InfoListWidget.WARNING, _elec_cur_B_abnormal, self.warning_publish)
        self.warn_44 = WarningClass("汇流条B电压异常", 60, InfoListWidget.WARNING, _elec_vol_B_abnormal, self.warning_publish)
        self.warn_45 = WarningClass("蓄电池电流异常", 60, InfoListWidget.WARNING, _elec_cur_bat_abnormal, self.warning_publish)
        # self.warn_46 = WarningClass("蓄电池电压异常", 60, InfoListWidget.WARNING, _fcc_disconnect, self.warning_publish)
        self.warn_47 = WarningClass("RTK定位故障", 30, InfoListWidget.WARNING, self._ins_rtk_invalid, self.warning_publish)
        self.warn_48 = WarningClass("连接丢失", 3, InfoListWidget.CRITICAL, _fcc_disconnect, self.warning_publish)

    def _adc_heat_fail(self):
        """
        空速管开关电源字状态和指令不一致
        """
        # if datahandler.connect_status and datahandler.elec_adc_heat_cmd >= 0:
        #     if datahandler.elec_adc_heat_cmd != self.adc_heat_status:
        #         if self.adc_heat_status_mismach_counter % 4 == 3:
        #             return True
        #         self.adc_heat_status_mismach_counter += 1
        #     else:
        #         self.adc_heat_status_mismach_counter = 0
        #         return False
        # else:
        return False

    def _ins_rtk_invalid(self):
        # (50, 'NARROW_INT'),
        # (51, 'RTK_DIRECT_INS'),
        # (54, 'INS_PSRDIFF'),
        # (55, 'INS_RTKFLOAT'),
        # (56, 'INS_RTKFIXED')
        if datahandler.connect_status:
            if self.state_pos == 50 \
                    or self.state_pos == 51 \
                    or self.state_pos == 54 \
                    or self.state_pos == 55 \
                    or self.state_pos == 56:
                return False
            else:
                return True
        else:
            return False

    def _brake_press_abnormal(self):
        if datahandler.connect_status:
            if self.breakl_percent > 30 and self.breakl_back_bar < 3 \
                    or self.breakr_percent > 30 and self.breakr_back_bar < 3:
                return True
            else:
                return False
        else:
            return False

    def _trust_servo_bias(self):
        if datahandler.connect_status:
            tmp = abs(self.trust_percent - self.trust_percent_back)

            if tmp >= 5:
                warnhandler.Eng_Servo.counter += 1
                if warnhandler.Eng_Servo.counter >= 3:
                    return True
                else:
                    return False
            else:
                warnhandler.Eng_Servo.counter = 0
                return False
        else:
            return False

    def _attitude_src_invalid(self):
        if datahandler.connect_status:
            if self.attitude_source == 0:
                return True
            else:
                return False
        else:
            return False

    def _nav_src_invalid(self):
        if datahandler.connect_status:
            if self.navigation_source == 0:
                return True
            else:
                return False
        else:
            return False

    def _height_src_invalid(self):
        if datahandler.connect_status:
            if self.height_source == 0:
                return True
            else:
                return False
        else:
            return False

    def _radar_invalid(self):
        if datahandler.connect_status:
            if self.radar1_connect == 0 \
                    and self.radar2_connect == 0 \
                    and self.radar3_connect == 0:
                return True
            else:
                return False
        else:
            return False

    def _engine_thr_abnormal(self):
        """
        EMU反馈Thr和设定值相差超过10%时提示

        """
        if datahandler.connect_status:
            tmp = abs(self.trust_percent - self.eng_thr)
            if tmp >= 5:
                warnhandler.Eng_Thr.counter += 1
                if warnhandler.Eng_Thr.counter >= 10:
                    return True
                else:
                    return False
            else:
                warnhandler.Eng_Thr.counter = 0
                return False
        else:
            return False

    def _engine_over_speed(self):
        """
        超转时提示

        """
        if datahandler.connect_status:
            if self.eng_rpm > 5250:
                return True
            else:
                return False
        else:
            return False

    def _adc_hdot_invalid(self):
        if datahandler.connect_status:
            if self.adc_connect == 0 or self.adc_hdot_invalid == 1:
                return True
            else:
                return False
        else:
            return False

    def _adc_vi_invalid(self):
        if datahandler.connect_status:
            if self.adc_connect == 0 or self.adc_vi_invalid == 1:
                return True
            else:
                return False
        else:
            return False

    def _adc_height_invalid(self):
        if datahandler.connect_status:
            if self.adc_connect == 0 or self.adc_height_invalid == 1:
                return True
            else:
                return False
        else:
            return False

    def warning_publish(self, warning_level, warning_str):

        tmpstr = time.strftime('[%H:%M:%S] ') + warning_str
        self.list_warnning_info.addStyledItem(tmpstr, warning_level)
        logging.warning(tmpstr)

    def timer_process_5Hz(self):
        self.counter += 1
        # if self.counter % 15 == 0:
        #     # TODO:实现告警信息检测逻辑并在告警信息栏添加相应的告警信息
        #     if not datahandler.connect_status:
        #         self.list_warnning_info.addStyledItem(time.strftime('[%H:%M:%S] ') + "连接丢失", InfoListWidget.CRITICAL)

        if self.counter % 5 == 0:
            if not datahandler.connect_status:  # 连接丢失标识提醒
                self.symbol_disable.setVisible(True)
                self.symbol_disable_2.setVisible(True)
                self.symbol_disable_3.setVisible(True)
            else:
                self.symbol_disable.setVisible(False)
                self.symbol_disable_2.setVisible(False)
                self.symbol_disable_3.setVisible(False)
            # 起飞前检查状态判断
            if datahandler.takeoff_check_finished:
                self.btn_fly_checklist.setStyleSheet('color: rgb(0, 0, 0);font: 12pt "Noto Sans S Chinese '
                                                     'Bold";background-color: rgb(0, 255, 0);')
                self.btn_fly_checklist.setText("飞行前检查已完成")
                self.tab4btn_takeoff.setEnabled(True)
                self.tab4btn_takeoff.setStyleSheet("background-color: rgb(34, 177, 76);")
            else:
                self.btn_fly_checklist.setStyleSheet('color: rgb(255, 255, 255);font: 12pt "Noto Sans S Chinese '
                                                     'Bold";background-color: rgb(255, 0, 0);')
                self.btn_fly_checklist.setText("进行飞行前检查")
                self.tab4btn_takeoff.setEnabled(False)
                self.tab4btn_takeoff.setStyleSheet("background-color: rgb(166, 166, 166);")

        time_str = time.strftime('%Y-%m-%d %H:%M:%S')
        # print(time_str)
        if self.navigation_source != 3:
            self.readout_utc_time.setText(time_str)

        warn_status_check(self.readout_air_temp, warnhandler.Eng_AirTmp.cur_warn_level)
        warn_status_check(self.readout_cyl2_temp, warnhandler.Eng_Cyl2Tmp.cur_warn_level)
        warn_status_check(self.readout_cyl3_temp, warnhandler.Eng_Cyl3Tmp.cur_warn_level)
        warn_status_check(self.readout_gas1_temp, warnhandler.Temp_Gas1.cur_warn_level)
        warn_status_check(self.readout_gas2_temp, warnhandler.Temp_Gas2.cur_warn_level)
        warn_status_check(self.readout_gas3_temp, warnhandler.Temp_Gas3.cur_warn_level)
        warn_status_check(self.readout_gas4_temp, warnhandler.Temp_Gas4.cur_warn_level)
        warn_status_check(self.readout_left_fuel, warnhandler.fuel_Left.cur_warn_level)
        warn_status_check(self.readout_right_fuel, warnhandler.Fuel_right.cur_warn_level)

        warn_status_check(self.readout_rpm, warnhandler.Eng_rpm.cur_warn_level)
        warn_status_check(self.readout_throttle, warnhandler.Eng_Thr.cur_warn_level)
        warn_status_check(self.readout_lube_temp, warnhandler.Eng_LubeTmp.cur_warn_level)
        warn_status_check(self.readout_lube_press, warnhandler.Eng_LubePress.cur_warn_level)
        warn_status_check(self.readout_fuel_press, warnhandler.Press_Fuel.cur_warn_level)

        # 滚转角指令和实际值相差较多时提示
        warn_status_check(self.readout_phi_deg, warnhandler.Phi_Track_Bias.cur_warn_level)
        # 俯仰角指令跟踪偏差大时提示
        warn_status_check(self.readout_theta_deg, warnhandler.Theta_Track_Bias.cur_warn_level)

        warn_status_check(self.readout_elel_deg, warnhandler.ELEL_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_eler_deg, warnhandler.ELER_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_rud_deg, warnhandler.RUD_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_trust_per, warnhandler.Eng_Thr.cur_warn_level)
        warn_status_check(self.readout_aill_deg, warnhandler.AILL_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_ailr_deg, warnhandler.AILR_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_flap, warnhandler.FLAP_Actuator_Bias.cur_warn_level)
        warn_status_check(self.readout_break_left, warnhandler.Brake_Press.cur_warn_level)
        warn_status_check(self.readout_break_right, warnhandler.Brake_Press.cur_warn_level)
        warn_status_check(self.readout_front_gear_deg, warnhandler.Gear_Actuator_Bias.cur_warn_level)

        warn_status_check(self.readout_ulink_upload, warnhandler.Ulink_Freq.cur_warn_level)
        warn_status_check(self.readout_llink_upload, warnhandler.Llink_Freq.cur_warn_level)
        warn_status_check(self.readout_glink_upload, warnhandler.Glink_Freq.cur_warn_level)
        warn_status_check(self.readout_download_link_status, warnhandler.Downlload_Freq.cur_warn_level)

    def setupGCSMainClass(self):
        self.setupDashBoard()
        self.setupPFDAera()

        # 当前选择油箱指示标志操作
        self.indicator_tank_select.setCuttentTank(1)

        datahandler.sig_RecvServoData.connect(self.servo_system_data_process)
        datahandler.sig_RecvFccSystmData.connect(self.fcc_system_data_process)
        datahandler.sig_RecvSensorINS.connect(self.sensor_mins_data_process)
        datahandler.sig_RecvSensorBINS.connect(self.sensor_bins_data_process)
        datahandler.sig_RecvSensorADC.connect(self.sensor_adc_data_process)
        datahandler.sig_RecvSensorRadar.connect(self.sensor_radar_data_process)
        datahandler.sig_RecvSensorGPS.connect(self.sensor_gps_data_process)
        datahandler.sig_RecvDataLink.connect(self.datalink_data_process)
        datahandler.sig_RecvElecSystem.connect(self.elec_system_data_process)
        datahandler.sig_RecvEngineSystem.connect(self.engine_system_data_process)
        datahandler.sig_RecvWarningSystem.connect(self.warnning_system_data_process)
        datahandler.sig_RecvCommandEcho.connect(self.command_echo_data_process)
        datahandler.sig_RecvEquipment.connect(self.equipment_data_process)

        datahandler.sig_pre_send_request.connect(self.pre_send_data_process)
        datahandler.sig_send_request.connect(self.send_data_process)
        datahandler.sig_request_echo.connect(self.request_echo_process)
        logging.info("主页面数据绑定完成")

        self.btn_remote_switch.clicked.connect(self.remote_switch)
        self.btn_loss_protect.clicked.connect(self.loss_protect)
        self.btn_fly_checklist.clicked.connect(self.fly_checklist_clicked)
        self.btn_clear_info.clicked.connect(self.list_cmd_history.clear)
        self.btn_clear_warnning_info.clicked.connect(self.list_warnning_info.clear)
        # 告警列表信息栏
        self.list_cmd_history.addStyledItem(time.strftime('[%H:%M:%S] ') + "地面站软件初始化完成", InfoListWidget.INFO)

        # 注册按钮响应事件
        self.reg_remote_cmd()

        # datahandler定时器启动
        datahandler.timer_init()

    def request_echo_process(self, echo_msg):
        try:
            if isinstance(echo_msg, str):
                self.readout_last_cmd_echo.setText(echo_msg)
                if echo_msg.endswith("失败"):  # 如果发送失败则在告警信息栏增加提示
                    self.list_warnning_info.addStyledItem(time.strftime('[%H:%M:%S] ') + echo_msg,
                                                          InfoListWidget.WARNING)
        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))

    def pre_send_data_process(self, msg_str):
        try:
            if isinstance(msg_str, str):
                self.readout_current_cmd.setText(msg_str)
            self.btn_send_command.setEnabled(True)
        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))

    def send_data_process(self, msg_str):
        try:
            if isinstance(msg_str, str):
                self.readout_last_send_cmd.setText(msg_str)
                # 在操作历史记录中增加记录
                self.list_cmd_history.addStyledItem(time.strftime('[%H:%M:%S] ') + msg_str, InfoListWidget.INFO)
            self.btn_send_command.setDisabled(True)
        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))

    def reg_remote_cmd(self):
        """
        注册按钮响应事件
        :return:
        """
        self.btn_cmd_reset.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RESET))
        self.btn_send_command.clicked.connect(lambda: datahandler.send_request())
        # TAB PAGE 1
        self.tab1btn_ground_test.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_GROUND_TEST))
        self.tab1btn_stop_test.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RESET))
        self.tab1btn_pre_stopengine.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_PRE_STOP))
        self.tab1btn_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_STOP))
        self.tab1btn_engine_slow.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_IDLING))
        self.tab1btn_engine_full.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_TAKE_OFF))
        self.tab1btn_lefttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEFT_OIL))
        self.tab1btn_righttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RIGHT_OIL))
        self.tab1btn_flap0.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_0))
        self.tab1btn_flap15.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_15))
        self.tab1btn_flap30.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_30))
        self.tab1btn_flap45.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_45))
        self.tab1btn_theta_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_PITCH, self.tab1edit_thetamix.value()))
        self.tab1btn_fg_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_FRONT_WHEEL_DEG, self.tab1edit_fg_mix.value()))
        self.tab1btn_ail_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_AILERON_RUDDER, self.tab1edit_ail_mix.value()))
        self.tab1btn_break_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_BRAKE,
                                                     self.tab1edit_break_mix.value()))
        self.tab1btn_gama_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ROLL, self.tab1edit_gama_mix.value()))
        self.tab1btn_ele_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_LIFT_RUDDER, self.tab1edit_ele_mix.value()))
        self.tab1btn_rud_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_COURSE_RUDDER, self.tab1edit_rud_mix.value()))
        self.tab1btn_break_diff.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_DIFF,
                                                     self.tab1edit_break_diff.value()))
        # self.tab2btn_pre_startengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab2btn_startengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab2btn_pre_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_PRE_STOP))
        self.tab2btn_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_STOP))
        self.tab2btn_engine_slow.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_IDLING))
        self.tab2btn_engine_warm.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_SLIDE_SMALL))
        self.tab2btn_engine_cruise.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_CRUISE_SMALL))
        self.tab2btn_engine_takeoff.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_TAKE_OFF))
        # self.tab2btn_enrichment_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab2btn_enrichment_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab2btn_aux_pump_on.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OIL_PUMP_OPEN))
        self.tab2btn_aux_pump_off.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OIL_PUMP_CLOSE))
        self.tab2btn_switchA_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_A_CLOSE))
        self.tab2btn_switchB_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_B_CLOSE))
        self.tab2btn_switchAB_on.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_ALL_DISCONNECT))
        self.tab2btn_lefttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEFT_OIL))
        self.tab2btn_lube_radiator_off.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEFT_OIL))
        # self.tab2btn_lube_radiator_half.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab2btn_lube_radiator_open.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab2btn_righttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RIGHT_OIL))
        self.tab2btn_break_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_BRAKE,
                                                     self.tab2edit_break_mix.value()))
        self.tab2btn_break_diff.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_DIFF,
                                                     self.tab2edit_break_diff.value()))
        self.tab2btn_fuel_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_THR, self.tab2edit_fuel_mix.value()))
        self.tab3btn_ready.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_ANGLE_OF_TAKEOFF))
        self.tab3btn_pre_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_PRE_STOP))
        self.tab3btn_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_STOP))
        self.tab3btn_taxi_in_runway.clicked.connect(lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_TAXI_IN,
                                                                                             [
                                                                                                 self.tab3edit_in_rwy_id.value(),
                                                                                                 self.tab3edit_in_port_id.value()]))
        self.tab3btn_engine_slow.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_IDLING))
        self.tab3btn_engine_warm.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_SLIDE_SMALL))
        self.tab3btn_engine_cruse1.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_CRUISE_SMALL))
        self.tab3btn_engine_cruse2.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_CRUISE_BIG))
        self.tab3btn_engine_climb.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_CLIMB))
        self.tab3btn_engine_full.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_TAKE_OFF))
        self.tab3btn_taxi_stop.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_BRAKING))
        self.tab3btn_taxi_start.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_TAXI, self.tab3edit_taxi_spd_mps.value()))
        self.tab3btn_break_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_BRAKE,
                                                     self.tab3edit_break_mix.value()))
        self.tab3btn_break_diff.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_DIFF,
                                                     self.tab3edit_break_diff.value()))
        self.tab3btn_taxi_out_runway.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_TAXI_OUT, [self.tab3edit_out_rwy_id.value(),
                                                                                  self.tab3edit_out_port_id.value()]))
        self.tab4btn_ready.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_ANGLE_OF_TAKEOFF))
        self.tab4btn_takeoff.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_TAKE_OFF))
        self.tab4btn_fly_level.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEVEL_FLIGHT))
        self.tab4btn_turnleft.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_TURN_LEFT))
        self.tab4btn_pre_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_PRE_STOP))
        self.tab4btn_stopengine.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_STOP))
        self.tab4btn_climb.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_CLIMB_UP))
        self.tab4btn_fly_straight.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_DIRECT_FLIGHT))
        self.tab4btn_break_takeoff.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_BRAKING))
        self.tab4btn_break.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_BRAKING))
        self.tab4btn_dive.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_SLIDE))
        self.tab4btn_turnright.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_TURN_RIGHT))
        self.tab4btn_lefttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEFT_OIL))
        self.tab4btn_righttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RIGHT_OIL))
        self.tab4btn_radar_enable.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RADAR_ENABLED))
        self.tab4btn_disable.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RADAR_DISABLED))
        self.tab4btn_flap0.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_0))
        self.tab4btn_flap15.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_15))
        self.tab4btn_flap30.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_30))
        # self.tab4btn_guid_exit.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab4btn_hover.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_CIRCLE))
        self.tab4btn_refly.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_GO_AROUND))
        self.tab4btn_navigation.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_NAVI))
        self.tab4btn_airway_height_set.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ROUTE_ALT, self.tab4edit_airway_height.value()))
        self.tab4btn_dot_mix.clicked.connect(lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ROUTE_NUM,
                                                                                      [self.tab4edit_airway_id.value(),
                                                                                       self.tab4edit_airdot_id.value()]))
        self.tab4btn_break_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_BACK_WHEEL_BRAKE,
                                                     self.tab4edit_break_mix.value()))
        self.tab4btn_online_dot_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ROUTE_ENTER,
                                                     self.tab4edit_online_airdot_id.value()))
        self.tab4btn_dy_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_YAW, self.tab4edit_dy_mix.value()))
        self.tab4btn_vi_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_AIR_SPEED, self.tab4edit_vi_mix.value()))
        self.tab4btn_gama_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ROLL, self.tab4edit_gama_mix.value()))
        self.tab4btn_theta_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_PITCH, self.tab4edit_theta_mix.value()))
        self.tab4btn_throttle_mix.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_THR, self.tab4edit_throttle_mix.value()))
        self.tab4btn_engine_full.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_THR_TAKE_OFF))

        self.tab5btn_adc_heat_on.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OUTPUT_B_OPEN))
        self.tab5btn_adc_heat_off.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OUTPUT_B_CLOSE))
        # self.tab5btn_nav_light_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_nav_light_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_lube_radiator_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_land_light_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_land_light_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_sce_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_sce_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_lube_radiator_half.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_parachute_power_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_parachute_power_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_parachute_pre_open.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_parachute_open.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_lube_radiator_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab5btn_flap0.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_0))
        self.tab5btn_flap15.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_15))
        self.tab5btn_flap30.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_30))
        self.tab5btn_flap45.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_FLAP_MOTOR_45))
        self.tab5btn_aux_pump_on.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OIL_PUMP_OPEN))
        self.tab5btn_aux_pump_off.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_OIL_PUMP_CLOSE))
        # self.tab5btn_enrichment_power_on.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_enrichment_power_off.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        self.tab5btn_lefttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LEFT_OIL))
        self.tab5btn_righttank.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_RIGHT_OIL))
        # self.tab5btn_vhf_poweron.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_vhf_poweroff.clicked.connect(lambda: datahandler.pre_send_request_cmd(0, COMMAND_CTRL_))
        # self.tab5btn_QNH_set.clicked.connect(lambda: datahandler.pre_send_request_cmd(1, COMMAND_CTRL_))
        # self.tab5btn_atc_code_set.clicked.connect(lambda: datahandler.pre_send_request_cmd(1, COMMAND_CTRL_))
        self.tab5btn_adc2heat_ctrl.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ADC2_HEATING,
                                                     self.tab5selection_adc2heat_cmd.currentIndex()))
        self.tab5btn_adc2vi_reset.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ADC2_VIAS_RESET,
                                                     self.tab5selection_adc2vi_reset.currentIndex()))
        self.tab5btn_windangle_reset.clicked.connect(
            lambda: datahandler.pre_send_request_cmd(1, COMMAND_ADJUST_ADC2_AOA_RESET,
                                                     self.tab5selection_windangle_reset.currentIndex()))

        # 注册传感器数据源切换按钮事件
        self.btn_att_src_ins.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_MASTER_ANGLE))
        self.btn_att_src_bins.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_SEC_ANGLE))

        self.btn_alt_src_adc.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_AIR_PRESSURE_ALT))
        self.btn_alt_src_gnss.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_GPS_ALT))
        self.btn_alt_src_ins.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_MASTER_ALT))

        self.btn_nav_src_ins.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_MASTER_POS))
        self.btn_nav_src_gnss.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_GPS_POS))
        self.btn_nav_src_bins.clicked.connect(
            lambda: datahandler.direct_send_request(0, COMMAND_CTRL_LINK_SEC_POS))

    # def reset_btn_clicked(self):
    #     reply = QMessageBox.question(None, '警告', '确定要复位?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
    #     if reply == QMessageBox.Yes:

    def fly_checklist_clicked(self):
        self.takeoff_checklist_pad.show()
        self.takeoff_checklist_pad.raise_()

    def loss_protect(self):
        """
        发送开关链路保护功能的命令

        :return:
        """
        if self.link_protect == 0:
            # 发送开启链路保护的命令到mqtt服务器
            self.cmd_send = datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LOSS_PRO_ON)
            logging.info("开启链路保护")
        else:
            # 发送关闭链路保护的命令到mqtt服务器
            self.cmd_send = datahandler.pre_send_request_cmd(0, COMMAND_CTRL_LOSS_PRO_OFF)
            logging.info("关闭链路保护")
        # print(self.cmd_send)
        if self.remote_upload_on == 1:
            datahandler.send_request(self.cmd_send)

    def remote_switch(self):

        # pixmapsrc = "resources/btn_command_on.png"

        if self.remote_upload_on == 0:
            self.remote_upload_on = 1
            pixmapsrc = "resources/btn_command_on.png"
            self.tabWidget.setDisabled(False)
            self.btn_send_command.setDisabled(True)  # 发送按钮只有在有待发送命令时激活
            self.btn_cmd_reset.setDisabled(False)
            self.btn_loss_protect.setDisabled(False)

        else:
            self.remote_upload_on = 0
            pixmapsrc = "resources/btn_command_off.png"
            self.tabWidget.setDisabled(True)
            self.btn_send_command.setDisabled(True)
            self.btn_cmd_reset.setDisabled(True)
            self.btn_loss_protect.setDisabled(True)

        self.btn_remote_switch.setIcon(QtGui.QIcon(pixmapsrc))
        datahandler.upload_switch(self.remote_upload_on)

        logging.info("设置遥控上行开关 remote_upload_on = %d", self.remote_upload_on)

    # 仪表盘区域初始化
    def setupDashBoard(self):
        # 初始化仪表盘
        # 转速表初始化
        self.dashboard_rpm.maxValue = 6000
        self.dashboard_rpm.minValue = 0
        self.dashboard_rpm.startAngle = 45
        self.dashboard_rpm.endAngle = 90
        self.dashboard_rpm.scaleMajor = 4
        self.dashboard_rpm.startPieRatio = 0.27
        self.dashboard_rpm.midPieRatio = 0.61
        self.dashboard_rpm.endPieRatio = 0.12
        self.dashboard_rpm.unitStr = ""
        self.dashboard_rpm.digitCount = 4
        self.dashboard_rpm.currentValue = 5123  # 可通过setValue槽连接
        self.dashboard_rpm.lcd.setVisible(False)
        self.dashboard_rpm.pieColorStart = QColor(255, 255, 255)  # 白色
        self.dashboard_rpm.pieColorMid = QColor(255, 255, 255)  # 白色
        self.dashboard_rpm.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_rpm.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_rpm.textRingRadious = 63
        self.dashboard_rpm.scaleLineLength = 10
        self.dashboard_rpm.pointerLength = 80
        self.dashboard_rpm.pointerColor = QColor(0, 255, 0)
        self.dashboard_rpm.scaleFontColor = QColor(255, 255, 255)

        self.readout_rpm.readoutUintStr = "rpm"
        self.readout_rpm.setIntValue(5123)

        # 油门仪表初始化
        self.dashboard_throttle.maxValue = 120
        self.dashboard_throttle.minValue = 0
        self.dashboard_throttle.startAngle = 45
        self.dashboard_throttle.endAngle = 90
        self.dashboard_throttle.scaleMajor = 6
        self.dashboard_throttle.startPieRatio = 0
        self.dashboard_throttle.midPieRatio = 0.833
        self.dashboard_throttle.endPieRatio = 0.167
        self.dashboard_throttle.unitStr = ""
        self.dashboard_throttle.digitCount = 4
        self.dashboard_throttle.currentValue = 110  # 可通过setValue槽连接
        self.dashboard_throttle.lcd.setVisible(False)
        self.dashboard_throttle.pieColorMid = QColor(255, 255, 255)  # 白色
        # self.dashboard_throttle.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_throttle.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_throttle.textRingRadious = 63
        self.dashboard_throttle.scaleLineLength = 10
        self.dashboard_throttle.pointerLength = 80
        self.dashboard_throttle.pointerColor = QColor(0, 255, 0)
        self.dashboard_throttle.scaleFontColor = QColor(255, 255, 255)

        self.readout_throttle.readoutDecimal = 1
        self.readout_throttle.readoutUintStr = "%"
        self.readout_throttle.setFloatValue(114.5)

        # 滑油温度仪表初始化
        self.dashboard_lube_temp.maxValue = 150
        self.dashboard_lube_temp.minValue = 0
        self.dashboard_lube_temp.startAngle = 45
        self.dashboard_lube_temp.endAngle = 90
        self.dashboard_lube_temp.scaleMajor = 3
        self.dashboard_lube_temp.startPieRatio = 0.333
        self.dashboard_lube_temp.midPieRatio = 0.467
        self.dashboard_lube_temp.endPieRatio = 0.2
        self.dashboard_lube_temp.unitStr = ""
        self.dashboard_lube_temp.digitCount = 4
        self.dashboard_lube_temp.currentValue = 99  # 可通过setValue槽连接
        self.dashboard_lube_temp.lcd.setVisible(False)
        self.dashboard_lube_temp.pieColorStart = QColor(255, 255, 255)  # 白色
        self.dashboard_lube_temp.pieColorMid = QColor(255, 255, 255)  # 白色
        self.dashboard_lube_temp.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_lube_temp.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_lube_temp.textRingRadious = 63
        self.dashboard_lube_temp.scaleLineLength = 10
        self.dashboard_lube_temp.pointerLength = 80
        self.dashboard_lube_temp.pointerColor = QColor(0, 255, 0)
        self.dashboard_lube_temp.scaleFontColor = QColor(255, 255, 255)

        self.readout_lube_temp.readoutUintStr = "℃"
        self.readout_lube_temp.setIntValue(99)

        # 滑油温度仪表初始化
        self.dashboard_lube_press.maxValue = 8
        self.dashboard_lube_press.minValue = 0
        self.dashboard_lube_press.startAngle = 45
        self.dashboard_lube_press.endAngle = 90
        self.dashboard_lube_press.scaleMajor = 4
        self.dashboard_lube_press.startPieRatio = 0.25
        self.dashboard_lube_press.midPieRatio = 0.6
        self.dashboard_lube_press.endPieRatio = 0.15
        self.dashboard_lube_press.unitStr = ""
        self.dashboard_lube_press.digitCount = 4
        self.dashboard_lube_press.currentValue = 3.99  # 可通过setValue槽连接
        self.dashboard_lube_press.lcd.setVisible(False)
        self.dashboard_lube_press.pieColorStart = QColor(255, 255, 255)  # 红色
        self.dashboard_lube_press.pieColorMid = QColor(255, 255, 255)  # 白色
        self.dashboard_lube_press.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_lube_press.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_lube_press.textRingRadious = 63
        self.dashboard_lube_press.scaleLineLength = 10
        self.dashboard_lube_press.pointerLength = 80
        self.dashboard_lube_press.pointerColor = QColor(0, 255, 0)
        self.dashboard_lube_press.scaleFontColor = QColor(255, 255, 255)

        self.readout_lube_press.readoutUintStr = "bar"
        self.readout_lube_press.readoutDecimal = 2
        self.readout_lube_press.setFloatValue(3.99)

        # 燃油消耗率仪表初始化
        self.dashboard_fuel_consum.maxValue = 25
        self.dashboard_fuel_consum.minValue = 0
        self.dashboard_fuel_consum.startAngle = 45
        self.dashboard_fuel_consum.endAngle = 90
        self.dashboard_fuel_consum.scaleMajor = 5
        self.dashboard_fuel_consum.startPieRatio = 0.1
        self.dashboard_fuel_consum.midPieRatio = 0.8
        self.dashboard_fuel_consum.endPieRatio = 0.1
        self.dashboard_fuel_consum.unitStr = ""
        self.dashboard_fuel_consum.digitCount = 4
        self.dashboard_fuel_consum.currentValue = 18.50  # 可通过setValue槽连接
        self.dashboard_fuel_consum.lcd.setVisible(False)
        self.dashboard_fuel_consum.pieColorStart = QColor(255, 255, 255)  # 红色
        self.dashboard_fuel_consum.pieColorMid = QColor(255, 255, 255)  # 白色
        self.dashboard_fuel_consum.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_fuel_consum.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_fuel_consum.textRingRadious = 63
        self.dashboard_fuel_consum.scaleLineLength = 10
        self.dashboard_fuel_consum.pointerLength = 80
        self.dashboard_fuel_consum.pointerColor = QColor(0, 255, 0)
        self.dashboard_fuel_consum.scaleFontColor = QColor(255, 255, 255)

        self.readout_fuel_custom.readoutUintStr = "L/h"
        self.readout_fuel_custom.readoutDecimal = 2
        self.readout_fuel_custom.setFloatValue(18.59)

        # 燃油压力仪表初始化
        self.dashboard_fuel_press.maxValue = 15
        self.dashboard_fuel_press.minValue = 0
        self.dashboard_fuel_press.startAngle = 45
        self.dashboard_fuel_press.endAngle = 90
        self.dashboard_fuel_press.scaleMajor = 5
        self.dashboard_fuel_press.startPieRatio = 0.2
        self.dashboard_fuel_press.midPieRatio = 0.6
        self.dashboard_fuel_press.endPieRatio = 0.2
        self.dashboard_fuel_press.unitStr = ""
        self.dashboard_fuel_press.digitCount = 4
        self.dashboard_fuel_press.currentValue = 11.20  # 可通过setValue槽连接
        self.dashboard_fuel_press.lcd.setVisible(False)
        self.dashboard_fuel_press.pieColorStart = QColor(255, 255, 255)
        self.dashboard_fuel_press.pieColorMid = QColor(255, 255, 255)  # 白色
        self.dashboard_fuel_press.ringOuterRadius = 100  # 圆环外圈半径
        self.dashboard_fuel_press.ringInnerRadius = 94  # 圆环内卷半径
        self.dashboard_fuel_press.textRingRadious = 63
        self.dashboard_fuel_press.scaleLineLength = 10
        self.dashboard_fuel_press.pointerLength = 80
        self.dashboard_fuel_press.pointerColor = QColor(0, 255, 0)
        self.dashboard_fuel_press.scaleFontColor = QColor(255, 255, 255)

        self.readout_fuel_press.readoutUintStr = "Psi"
        self.readout_fuel_press.readoutDecimal = 2
        self.readout_fuel_press.setFloatValue(11.2)

    # 中央水平仪区域初始化
    def setupPFDAera(self):
        # 初始化PFD仪表显示区域
        # 速度尺初始化
        self.meter_speed.minValue = -1
        self.meter_speed.maxValue = 500
        self.meter_speed.ColorBarWidthRatio = 0.1
        self.meter_speed.pointerWidthRatio = 0.75
        self.meter_speed.lateralDirection = 0  # 颜色条在右侧
        self.meter_speed.region2MaxValue = 200
        self.meter_speed.region2MinValue = 90
        self.meter_speed.viewLength = 60
        self.meter_speed.setValue(80)
        self.meter_speed.setTargetValue(SPEED_V1, SPEED_V2)
        self.meter_speed.target1_text = SPEED_V1_TEXT
        self.meter_speed.target2_text = SPEED_V2_TEXT
        self.meter_speed.pointerHeightRatio = 0.05
        self.meter_speed.pointerWidthRatio = 0.8
        # 高度尺初始化
        self.meter_height.minValue = -501
        self.meter_height.maxValue = 10000
        self.meter_height.ColorBarWidthRatio = 0.0
        self.meter_height.pointerWidthRatio = 0.75
        self.meter_height.lateralDirection = 1  # 颜色条在左侧
        self.meter_height.region2MaxValue = 5000
        self.meter_height.region2MinValue = 1500
        self.meter_height.viewLength = 600
        self.meter_height.scaleUnit = 100
        self.meter_height.setValue(1650)
        self.meter_height.setTargetValue(-500, -500)
        self.meter_height.pointerHeightRatio = 0.05
        self.meter_height.pointerWidthRatio = 0.8
        # 航向尺初始化
        self.meter_heading.pointerWidthRatio = 0.03
        self.meter_heading.setValue(0)
        # self.meter_heading.setTargetValue(0)
        self.meter_heading.targetWidthRatio = 0.04
        self.meter_heading.targetHeightRatio = 0.2
        self.viewLength = 15
        # 水平仪初始化
        self.meter_center_pfd.scaleLenRatio = 0.45
        self.meter_center_pfd.rollScaleRadiusRatio = 0.34
        self.meter_center_pfd.setThetaDeg(-10)
        self.meter_center_pfd.setPhiDeg(15)

    # 界面接收到舵系统数据后更新界面
    # data为json格式数据 见：servo_system的定义
    def servo_system_data_process(self, data):
        # 根据接收到的舵系统数据更新UI
        try:
            elel_deg = data["elel_deg"]
            elel_deg_back = data["elel_deg_back"]
            warnhandler.ELEL_Actuator_Bias.warn_level(elel_deg - elel_deg_back)
            eler_deg = data["eler_deg"]
            eler_deg_back = data["eler_deg_back"]
            warnhandler.ELER_Actuator_Bias.warn_level(eler_deg - eler_deg_back)
            aill_deg = data["aill_deg"]
            aill_deg_back = data["aill_deg_back"]
            warnhandler.AILL_Actuator_Bias.warn_level(aill_deg - aill_deg_back)
            ailr_deg = data["ailr_deg"]
            ailr_deg_back = data["ailr_deg_back"]
            warnhandler.AILR_Actuator_Bias.warn_level(ailr_deg - ailr_deg_back)
            rud_deg = data["rud_deg"]
            warnhandler.Rudder_Stuck.warn_level(rud_deg)
            rud_deg_back = data["rud_deg_back"]
            warnhandler.RUD_Actuator_Bias.warn_level(rud_deg - rud_deg_back)
            self.trust_percent = data["trust_percent"]
            self.trust_percent_back = data["trust_percent_back"]
            self.breakl_percent = data["breakl_percent"]
            self.breakl_back_bar = data["breakl_back_bar"]
            # warnhandler.Brake_Press.warn_level(breakl_back_bar)
            self.breakr_percent = data["breakr_percent"]
            self.breakr_back_bar = data["breakr_back_bar"]
            warnhandler.Brake_Press.warn_level(self.breakr_back_bar)
            frontwheel_deg = data["frontwheel_deg"]
            frontwheel_deg_back = data["frontwheel_deg_back"]
            warnhandler.Gear_Actuator_Bias.warn_level(frontwheel_deg - frontwheel_deg_back)
            flap_deg = data["flap_deg"]
            flap_deg_back = data["flap_deg_back"]
            warnhandler.FLAP_Actuator_Bias.warn_level(flap_deg - flap_deg_back)

            tmpstr = "%5.2f/%5.2f" % (elel_deg, elel_deg_back)
            self.readout_elel_deg.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (eler_deg, eler_deg_back)
            self.readout_eler_deg.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (rud_deg, rud_deg_back)
            self.readout_rud_deg.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (aill_deg, aill_deg_back)
            self.readout_aill_deg.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (ailr_deg, ailr_deg_back)
            self.readout_ailr_deg.setText(tmpstr)

            tmpstr = "%5.1f/%5.1f" % (flap_deg, flap_deg_back)
            self.readout_flap.setText(tmpstr)

            tmpstr = "%5.1f/%5.1f" % (self.trust_percent, self.trust_percent_back)
            self.readout_trust_per.setText(tmpstr)

            tmpstr = "%5.1f/%5.2f" % (self.breakl_percent, self.breakl_back_bar)
            self.readout_break_left.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (self.breakr_percent, self.breakr_back_bar)
            self.readout_break_right.setText(tmpstr)

            tmpstr = "%5.2f/%5.2f" % (frontwheel_deg, frontwheel_deg_back)
            self.readout_front_gear_deg.setText(tmpstr)

            total_press = 20
            self.indicator_gearsystem.setBreakPressPercent(self.breakl_back_bar / total_press,
                                                           self.breakr_back_bar / total_press)

        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))
        # print(data)

    def fcc_system_data_process(self, data):
        # 根据接收到的舵系统数据更新UI
        try:
            # 飞控系统信息显示
            system_info = data["system_info"]
            cpu_useage = system_info["cpu_useage"]
            fcc_start_sec = system_info["fcc_start_sec"]  # 需转换为时分秒显示
            fly_start_sec = system_info["fly_start_sec"]  # 需转换为时分秒显示
            software_version = system_info["software_version"]
            start_hour = fcc_start_sec / 3600
            start_min = (fcc_start_sec % 3600) / 60
            start_sec = fcc_start_sec % 60
            self.readout_fcc_work_time.setText("%02d:%02d:%02d" % (start_hour, start_min, start_sec))

            route_flight = data["route_flight"]
            airline_number = route_flight["airline_number"]
            dot_number = route_flight["dot_number"]
            dx_m = route_flight["dx_m"]
            dy_m = route_flight["dy_m"]
            dh_m = route_flight["dh_m"]
            dpsi_deg = route_flight["dpsi_deg"]

            control_mode = data["control_mode"]
            fcc_config_mode = control_mode["fcc_config_mode"]  # 飞控装订模式，滑行或飞行模式  1:滑行模式 0：飞行模式
            is_in_taxi_mode = control_mode["is_in_taxi_mode"]  # 当前是否处于滑行模式 1-滑行中 0-不处于滑行状态
            vertical_fly_mode = control_mode["vertical_fly_mode"]  # 纵向飞行模态 00:无定义 01:平飞 10:爬升 11:下滑
            lateral_fly_mode = control_mode["lateral_mode"]  # 横向飞行模态 00:无定义 01:直飞10:向左 11:向右
            link_protect = control_mode["link_protect"]  # 1：链路保护开，0：链路保护关
            on_way_fly_mode = control_mode["on_way_fly_mode"]  # 在线航路飞行中 0-非在线航路飞行 1-在线航路飞行
            fly_mode = control_mode["fly_mode"]  # 000：人工引导模态 001：点号进入模态 010：航线飞行模态 011：盘旋模态
            # 100：归航模态 101：着陆模态 110：低空飞行模态 111：起飞模态
            in_takeoff_mode = control_mode["in_takeoff_mode"]  # 起飞状态： 1：起飞（绿灯） 0：（灰色）
            in_land_mode = control_mode["in_land_mode"]  # 着陆状态： 1：着陆（绿灯） 0：（灰色）
            nav_mode = control_mode["nav_mode"]  # 00：指令遥控01：一维导航 10：二维导航 11：三维导航
            pre_nav = control_mode["pre_nav"]  # 预导航开关 1：预导航 0：未开启预导航
            on_air = control_mode["on_air"]  # 空地状态 1：空中（绿灯） 0：地面（红灯）
            on_reset = control_mode["on_reset"]  # 复位状态 1：复位（绿灯） 0：（红灯）
            on_taxi_correct = control_mode["on_taxi_correct"]  # 1：纠偏（绿灯）0：（红灯）
            engine_pre_stop = control_mode["engine_pre_stop"]  # 1：发动机预停车（绿灯）0：（红灯） 绿灯亮起时才响应停车指令
            engine_ctrl_mode = control_mode["engine_ctrl_mode"]  # 油门控制模式 0：最小油门，1：起飞油门，2：爬升油门，
            # 3：巡航大油门，4：巡航中油门，5：巡航小油门，
            # 6：下滑大油门，7：下滑小油门，8：怠速油门，9：停车

            # 飞控装订模式显示
            tmp_text = "无效状态"
            self.readout_fcc_config_mode.setStyleSheet("color: rgb(255, 255, 255);")
            if fcc_config_mode == 1:
                tmp_text = "滑行模式"
            elif fcc_config_mode == 0:
                tmp_text = "飞行模式"
            else:
                self.readout_fcc_config_mode.setStyleSheet("color: rgb(255, 0, 0);")

            self.readout_fcc_config_mode.setText(tmp_text)

            # 滑行状态指示
            if is_in_taxi_mode == 1:
                self.led_in_taximode.setStatus(WidgetLED.LED_ENABLE)
                # 当处于滑行模式但是纠偏未接入时设置为红色告警颜色
                if on_taxi_correct == 1:
                    self.led_taxi_control.setStatus(WidgetLED.LED_ENABLE)
                else:
                    self.led_taxi_control.setStatus(WidgetLED.LED_WARNNING)
            else:
                self.led_in_taximode.setStatus(WidgetLED.LED_DISABLE)
                if on_taxi_correct == 1:
                    self.led_taxi_control.setStatus(WidgetLED.LED_ENABLE)
                else:
                    self.led_taxi_control.setStatus(WidgetLED.LED_DISABLE)

            # 纵向飞行模态显示
            tmp_str = "无定义"
            str_list = ["无定义", "平飞", "爬升", "下滑"]
            try:
                tmp_str = str_list[vertical_fly_mode]
            except Exception as e:
                logging.warning("invalid vertical_fly_mode:%d", vertical_fly_mode)
            self.readout_lon_mode.setText(tmp_str)

            # 横向飞行模态显示
            tmp_str = "无定义"
            str_list = ["无定义", "直飞", "向左", "向右"]
            try:
                tmp_str = str_list[lateral_fly_mode]
            except Exception as e:
                logging.warning("invalid lateral_fly_mode:%d", lateral_fly_mode)
            self.readout_lat_mode.setText(tmp_str)

            # 链路保护开关提示
            pixmapsrc = "resources/btn_command_off.png"
            if link_protect == 1:
                pixmapsrc = "resources/btn_command_on.png"
            else:
                pixmapsrc = "resources/btn_command_off.png"
            self.btn_loss_protect.setIcon(QtGui.QIcon(pixmapsrc))
            self.link_protect = link_protect  # 将链路保护开关状态保存到窗体变量供其他函数访问

            # 在线航线飞行LED提示
            if on_way_fly_mode == 1:
                self.led_fly_on_way.setStatus(WidgetLED.LED_ENABLE)
            else:
                self.led_fly_on_way.setStatus(WidgetLED.LED_DISABLE)

            # 飞行引导模态提示
            tmp_str = "无定义"
            str_list = [
                "人工引导",
                "点号进入",
                "航线飞行",
                "盘旋",
                "归航",
                "着陆",
                "低空飞行",
                "起飞"]
            try:
                tmp_str = str_list[fly_mode]
            except Exception as e:
                logging.warning("invalid fly_mode value:%d", fly_mode)
            self.readout_fly_mode.setText(tmp_str)

            # 起飞状态标识
            if in_takeoff_mode == 1:
                self.led_takeoff.setStatus(WidgetLED.LED_ENABLE)
            else:
                self.led_takeoff.setStatus(WidgetLED.LED_DISABLE)
            # 着陆程序标识
            if in_land_mode == 1:
                self.led_is_landing.setStatus(WidgetLED.LED_ENABLE)
            else:
                self.led_is_landing.setStatus(WidgetLED.LED_DISABLE)

            # 导航模式显示
            tmp_str = "指令遥控"
            str_list = [
                "指令遥控",
                "一维导航",
                "二维导航",
                "三维导航"]
            try:
                tmp_str = str_list[nav_mode]
            except Exception as e:
                logging.warning("invalid nav_mode value:%d", nav_mode)
            self.readout_nav_mode.setText(tmp_str)

            if pre_nav == 1:
                self.led_pre_nav.setStatus(WidgetLED.LED_ENABLE)
            else:
                self.led_pre_nav.setStatus(WidgetLED.LED_DISABLE)

            if on_air == 1:
                self.led_is_on_air.setText("空中")
                self.led_is_on_air.setStyleSheet('background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, '
                                                 'y2:1, stop:0 rgba(0, 255, 0, 255), stop:1 rgba(0, 137, 0, '
                                                 '255));font: 75 12pt "Noto Sans S Chinese Bold";color: rgb(255, 255, '
                                                 '255);')
                # self.led_is_on_air.setStatus(WidgetLED.LED_ENABLE)
            else:
                self.led_is_on_air.setText("地面")
                self.led_is_on_air.setStyleSheet('background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, '
                                                 'y2:1, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(123, 0, 0, '
                                                 '255));font: 75 12pt "Noto Sans S Chinese Bold";color: rgb(255, 255, '
                                                 '255);')

            if on_reset == 1:  # 设置了复位状态后LED灯置为红色，标识当前为复位状态
                self.led_is_on_reset.setStatus(WidgetLED.LED_WARNNING)
            else:
                self.led_is_on_reset.setStatus(WidgetLED.LED_DISABLE)

            if engine_pre_stop == 1:  # 设置了预停车状态后，将LED设置为红色，标识当前为预停车状态
                self.led_pre_engine_stop.setStatus(WidgetLED.LED_WARNNING)
            else:
                self.led_pre_engine_stop.setStatus(WidgetLED.LED_DISABLE)

            tmp_str = "最小油门"
            str_list = [
                "最小油门",
                "起飞油门",
                "爬升油门",
                "巡航大油门",
                "巡航中油门",
                "巡航小油门",
                "下滑大油门",
                "下滑小油门",
                "怠速油门",
                "停车"]
            try:
                tmp_str = str_list[engine_ctrl_mode]
            except Exception as e:
                logging.warning("invalid engine_ctrl_mode value:%d", engine_ctrl_mode)
            self.readout_engine_ctrl_mode.setText(tmp_str)

            control_cmd = data["control_cmd"]
            phi_cmd_deg = control_cmd["phi_cmd_deg"]
            theta_cmd_deg = control_cmd["theta_cmd_deg"]
            height_cmd_m = control_cmd["height_cmd_m"]
            # heading_cmd_deg = control_cmd["heading_cmd_deg"]
            psi_cmd_deg = control_cmd["psi_cmd_deg"]
            # speed_cmd_mps = control_cmd["speed_cmd_mps"]
            speed_cmd_kmph = control_cmd["speed_cmd_kmph"]
            # dv_int_theta_deg = control_cmd["dv_int_theta_deg"]
            # dv_int_trust_deg = control_cmd["dv_int_trust_deg"]
            # dh_int_theta_deg = control_cmd["dh_int_theta_deg"]
            # dy_int_phi_deg = control_cmd["dy_int_phi_deg"]
            # dtheta_int_ele_deg = control_cmd["dtheta_int_ele_deg"]
            # dphi_int_ail_deg = control_cmd["dphi_int_ail_deg"]

            sensor_fusion = data["sensor_fusion"]
            self.attitude_source = sensor_fusion["attitude_source"]
            theta_deg = sensor_fusion["theta_deg"]
            phi_deg = sensor_fusion["phi_deg"]
            psi_deg = sensor_fusion["psi_deg"]  # 欧拉角，偏航角
            wx_dps = sensor_fusion["wx_dps"]
            wy_dps = sensor_fusion["wy_dps"]
            wz_dps = sensor_fusion["wz_dps"]
            acc_x = sensor_fusion["acc_x"]
            acc_y = sensor_fusion["acc_y"]
            acc_z = sensor_fusion["acc_z"]
            self.navigation_source = sensor_fusion["navigation_source"]
            lon_deg = sensor_fusion["lon_deg"]
            lat_deg = sensor_fusion["lat_deg"]
            vd_mps = sensor_fusion["vd_mps"]
            vi_mps = sensor_fusion["vi_mps"]
            heading_deg = sensor_fusion["heading_deg"]
            hdot_mps = sensor_fusion["hdot_mps"]
            self.height_source = sensor_fusion["height_source"]
            altitude_m = sensor_fusion["altitude_m"]
            ref_height_m = sensor_fusion["ref_height_m"]

            self.meter_center_pfd.setThetaDeg(theta_deg)
            self.meter_center_pfd.setPhiDeg(phi_deg)
            self.meter_heading.setValue(psi_deg)
            self.meter_heading.setTargetValue(psi_cmd_deg)
            self.readout_psi_deg.setText("%5.1f°" % heading_deg)
            self.readout_track_psi_deg.setText("%5.1f°" % psi_deg)

            self.readout_target_spd_kmph.setText("%5.1fkm/h" % speed_cmd_kmph)
            self.meter_speed.setValue(vi_mps * 3.6)
            # self.meter_speed.setTargetValue(speed_cmd_kmph)
            self.readout_current_spd_kmph.setText("%5.1fkm/h" % (vd_mps * 3.6))
            # self.readout_spd_vi_mps.setText("%5.1f" % vi_mps)
            # self.meter_height.setTargetValue(height_cmd_m)  # 高度计设置
            self.meter_height.setValue(altitude_m)
            self.readout_target_height_m.setText("%.1fm" % height_cmd_m)
            self.readout_hdot_mps.setText("%.1fm/s" % hdot_mps)

            # 姿态源显示
            if self.attitude_source == 0:
                self.btn_att_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_att_src_bins.setStyleSheet(self.btn_disable_style_sheet)
            elif self.attitude_source == 1:
                self.btn_att_src_ins.setStyleSheet(self.btn_enable_style_sheet)
                self.btn_att_src_bins.setStyleSheet(self.btn_disable_style_sheet)
            elif self.attitude_source == 2:
                self.btn_att_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_att_src_bins.setStyleSheet(self.btn_enable_style_sheet)

            # 滚转角指示
            tmp_str = "%4.1f°/%4.1f°" % (phi_deg, phi_cmd_deg)
            warnhandler.Phi_Track_Bias.warn_level(phi_deg - phi_cmd_deg)
            self.readout_phi_deg.setText(tmp_str)

            # 俯仰角角度指示
            tmp_str = "%4.1f°/%4.1f°" % (theta_deg, theta_cmd_deg)
            warnhandler.Theta_Track_Bias.warn_level(theta_deg - theta_cmd_deg)
            self.readout_theta_deg.setText(tmp_str)

            # 导航信号源
            if self.navigation_source == 0:
                self.btn_nav_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_bins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_gnss.setStyleSheet(self.btn_disable_style_sheet)
            elif self.navigation_source == 1:
                self.btn_nav_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_bins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_gnss.setStyleSheet(self.btn_enable_style_sheet)
            elif self.navigation_source == 2:
                self.btn_nav_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_bins.setStyleSheet(self.btn_enable_style_sheet)
                self.btn_nav_src_gnss.setStyleSheet(self.btn_disable_style_sheet)
            elif self.navigation_source == 3:
                self.btn_nav_src_ins.setStyleSheet(self.btn_enable_style_sheet)
                self.btn_nav_src_bins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_nav_src_gnss.setStyleSheet(self.btn_disable_style_sheet)

            # 高度信号源
            if self.height_source == 0:
                self.btn_alt_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_adc.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_gnss.setStyleSheet(self.btn_disable_style_sheet)
            elif self.height_source == 1:
                self.btn_alt_src_ins.setStyleSheet(self.btn_enable_style_sheet)
                self.btn_alt_src_adc.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_gnss.setStyleSheet(self.btn_disable_style_sheet)
            elif self.height_source == 2:
                self.btn_alt_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_adc.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_gnss.setStyleSheet(self.btn_enable_style_sheet)
            elif self.height_source == 3:
                self.btn_alt_src_ins.setStyleSheet(self.btn_disable_style_sheet)
                self.btn_alt_src_adc.setStyleSheet(self.btn_enable_style_sheet)
                self.btn_alt_src_gnss.setStyleSheet(self.btn_disable_style_sheet)
            # 机场高度标识
            origin_airport_info = data["origin_airport_info"]
            altitude_m = origin_airport_info["altitude_m"]
            self.readout_origion_apt_alt.setText("%dm" % altitude_m)

            dest_airport_info = data["dest_airport_info"]
            altitude_m = dest_airport_info["altitude_m"]
            qnh_m = dest_airport_info["qnh_m"]
            self.readout_dest_apt_alt.setText("%dm" % altitude_m)

        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))
        # print(data)

    def sensor_mins_data_process(self, data):
        try:
            freq = data["freq"]
            self.ins_state = data["ins_state"]
            ins_state_dict = dict(
                (
                    (0, '未启动'),
                    (1, '对准'),
                    (2, '低精度导航'),  # 但方位精度偏低
                    (3, '高精度导航'),
                    (4, '无GNSS导肮'),  # GNSS可能故障
                    (5, '刚进入导航'),
                    (6, '重力对准中'),
                    (7, '等待初始位置')
                )
            )
            tmp_str = ins_state_dict.get(self.ins_state, str(self.ins_state))
            self.readout_ins_status.setText(tmp_str)

            utc_time_year = data["utc_time_year"]
            utc_time_month = data["utc_time_month"]
            utc_time_day = data["utc_time_day"]
            utc_time_hour = data["utc_time_hour"]
            utc_time_min = data["utc_time_min"]
            utc_time_sec = data["utc_time_sec"]
            tmp_str = "%04d/%02d/%02d %02d:%02d:%02d" % (
                utc_time_year, utc_time_month, utc_time_day, utc_time_hour, utc_time_min, utc_time_sec)
            if self.navigation_source == 3:
                self.readout_utc_time.setText(tmp_str)

            state_vel = data["state_vel"]
            self.state_pos = data["state_pos"]
            position_state_name_dict = dict(
                (
                    (50, 'NARROW_INT'),
                    (51, 'RTK_DIRECT_INS'),
                    (52, 'INS_SBAS'),
                    (53, 'INS_PSRSP'),
                    (54, 'INS_PSRDIFF'),
                    (55, 'INS_RTKFLOAT'),
                    (56, 'INS_RTKFIXED')
                )
            )
            tmp_str = position_state_name_dict.get(self.state_pos, str(self.state_pos))
            if self.navigation_source == 3:  # 当导航数据源为主惯时显示主惯的定位状态
                self.readout_pos_status.setText(tmp_str)

            # wx_dps = data["wx_dps"]
            # wy_dps = data["wy_dps"]
            # wz_dps = data["wz_dps"]
            # acc_x = data["acc_x"]
            # acc_y = data["acc_y"]
            # acc_z = data["acc_z"]
            # vd_n_mps = data["vd_n_mps"]
            # vd_e_mps = data["vd_e_mps"]
            # vd_up_mps = data["vd_up_mps"]
            # hdot_mps = data["hdot_mps"]
            # vd_mps = data["vd_mps"]
            # theta_deg = data["theta_deg"]
            # phi_deg = data["phi_deg"]
            # psi_deg = data["psi_deg"]
            # heading_deg = data["heading_deg"]
            # lon_deg = data["lon_deg"]
            # lat_deg = data["lat_deg"]
            # sat_used = data["sat_used"]
            # sat_tracked = data["sat_tracked"]
            # gdop = data["gdop"]
            # pdop = data["pdop"]
            # hdop = data["hdop"]
            # vdop = data["vdop"]
            # tdop = data["tdop"]

        except Exception as e:
            logging.error(e.args)
            logging.error(str(e))
            logging.error(repr(e))

    def sensor_bins_data_process(self, data):
        pass

    def sensor_adc_data_process(self, data):
        try:
            self.adc_connect = data['adc_connect']
            self.adc_freq = data['freq']
            self.adc_ram_error = data['adc_ram_error']
            self.adc_mach_invalid = data['adc_mach_invalid']
            self.adc_hdot_invalid = data['adc_hdot_invalid']
            self.adc_vi_invalid = data['adc_vi_invalid']
            self.adc_height_invalid = data['adc_height_invalid']
            self.adc_total_press_invalid = data['adc_total_press_invalid']
            self.adc_static_press_invalid = data['adc_static_press_invalid']
            self.adc_normal = data['adc_normal']
            self.adc_height_m = data['height_m']
            self.adc_vi_mps = data['vi_mps']
            self.adc_mach = data['mach']
            self.adc_hdot_mps = data['hdot_mps']

        except Exception as e:
            logging.error(repr(e))

    def sensor_radar_data_process(self, data):
        try:
            if data['valid_radar_num'] > 0:
                self.readout_radar_alt.setText("雷达高度:%.1f" % data['ac_radar_alt'])
                self.readout_radar_alt.setVisible(True)
            else:
                self.readout_radar_alt.setVisible(False)

            self.radar1_connect = data['radar1_connect']
            self.radar2_connect = data['radar2_connect']
            self.radar3_connect = data['radar3_connect']

        except Exception as e:
            logging.error(repr(e))

    def sensor_gps_data_process(self, data):
        pass

    def datalink_data_process(self, data):
        try:
            l_link_upload_freq = data["l_link_upload_freq"]
            warnhandler.Llink_Freq.warn_level(l_link_upload_freq)
            u_link_upload_freq = data["u_link_upload_freq"]
            warnhandler.Ulink_Freq.warn_level(u_link_upload_freq)
            g_link_upload_freq = data["g_link_upload_freq"]
            warnhandler.Glink_Freq.warn_level(g_link_upload_freq)
            download_freq = data["download_freq"]
            warnhandler.Downlload_Freq.warn_level(download_freq)
            current_link_type = data["current_link_type"]

            self.readout_ulink_upload.setText("U%02d" % u_link_upload_freq)
            self.readout_llink_upload.setText("L%02d" % l_link_upload_freq)
            self.readout_glink_upload.setText("G%02d" % g_link_upload_freq)

            tmpstr = str(current_link_type) + "链路 " + str(download_freq) + "Hz"
            self.readout_download_link_status.setText(tmpstr)

        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))

    def elec_system_data_process(self, data):
        try:
            self.adc_heat_status = data["elec_circuit_B_on"]
        except Exception as e:
            logging.error(repr(e))

    def engine_system_data_process(self, data):
        try:
            self.eng_thr = data["trust_percent"]
            warnhandler.Eng_Thr.warn_level(self.eng_thr)
            self.eng_rpm = data["rpm"]
            press_air_hpa = data["press_air_hpa"]
            warnhandler.Press_Air.warn_level(press_air_hpa)
            press_env_hpa = data["press_env_hpa"]
            temp_air_degree = data["temp_air_degree"]
            warnhandler.Eng_AirTmp.warn_level(temp_air_degree)
            pos_servo_percent = data["pos_servo_percent"]
            press_cor_psi = data["press_cor_psi"]
            warnhandler.Eng_CorPress.warn_level(press_cor_psi)
            temp_cor_degree = data["temp_cor_degree"]
            warnhandler.Eng_CorTmp.warn_level(temp_cor_degree)
            press_limit_psi = data["press_limit_psi"]
            warnhandler.Eng_PressCmd.warn_level(press_limit_psi)
            temp_cyl2_degree = data["temp_cyl2_degree"]
            warnhandler.Eng_Cyl2Tmp.warn_level(temp_cyl2_degree)
            temp_cyl3_degree = data["temp_cyl3_degree"]
            warnhandler.Eng_Cyl3Tmp.warn_level(temp_cyl3_degree)
            temp_lube_degree = data["temp_lube_degree"]
            warnhandler.Eng_LubeTmp.warn_level(temp_lube_degree)
            press_lube_bar = data["press_lube_bar"]
            warnhandler.Eng_LubePress.warn_level(press_lube_bar)
            eng_vol_v = data["eng_vol_v"]
            temp_gen1_degree = data["temp_gen1_degree"]
            warnhandler.Eng_Gene1.warn_level(temp_gen1_degree)
            temp_gen2_degree = data["temp_gen2_degree"]
            warnhandler.Eng_Gene2.warn_level(temp_gen2_degree)
            lamp_boost = data["lamp_boost"]
            lamp_alarm = data["lamp_alarm"]
            status_boost = data["status_boost"]
            status_switch = data["status_switch"]
            error = data["error"]
            press_qg_hpa = data["press_qg_hpa"]
            press_fuel_psi = data["press_fuel_psi"]
            warnhandler.Press_Fuel.warn_level(press_fuel_psi)
            self.fuel_right_l = data["fuel_right_l"]
            warnhandler.Fuel_right.warn_level(self.fuel_right_l)
            self.fuel_left_l = data["fuel_left_l"]
            warnhandler.fuel_Left.warn_level(self.fuel_left_l)
            temp_gas1_degree = data["temp_gas1_degree"]
            warnhandler.Temp_Gas1.warn_level(temp_gas1_degree)
            temp_gas2_degree = data["temp_gas2_degree"]
            warnhandler.Temp_Gas2.warn_level(temp_gas2_degree)
            temp_gas3_degree = data["temp_gas3_degree"]
            warnhandler.Temp_Gas3.warn_level(temp_gas3_degree)
            temp_gas4_degree = data["temp_gas4_degree"]
            warnhandler.Temp_Gas4.warn_level(temp_gas4_degree)
            start_time_hour = data["start_time_hour"]
            start_time_min = data["start_time_min"]
            start_time_sec = data["start_time_sec"]
            total_time_hour = data["total_time_hour"]
            total_time_min = data["total_time_min"]
            total_time_sec = data["total_time_sec"]
            freq = data["emu_freq"]
            tank_selection = data['tank_selection']

            self.dashboard_rpm.setValue(self.eng_rpm)
            self.readout_rpm.setIntValue(self.eng_rpm)
            warnhandler.Eng_rpm.warn_level(self.eng_rpm)

            self.dashboard_throttle.setValue(self.eng_thr)
            self.readout_throttle.setFloatValue(self.eng_thr)

            self.dashboard_lube_temp.setValue(temp_lube_degree)
            self.readout_lube_temp.setIntValue(temp_lube_degree)

            self.dashboard_lube_press.setValue(press_lube_bar)
            self.readout_lube_press.setFloatValue(press_lube_bar)

            self.dashboard_fuel_press.setValue(press_fuel_psi)
            self.readout_fuel_press.setFloatValue(press_fuel_psi)

            # TODO:根据发动机的燃油消耗率曲线结合高度、速度、油门插值获得燃油消耗率
            # 或者是从油量传感器中获取相应的燃油消耗率
            fuel_consum_rate = self.eng_rpm / 5200.0 * 21.5
            self.dashboard_fuel_consum.setValue(fuel_consum_rate)
            self.readout_fuel_custom.setFloatValue(fuel_consum_rate)

            self.indicator_tank_select.setCuttentTank(tank_selection)
            if tank_selection == 1:
                self.indicator_tank_select.setCurrentWarnLevel(warnhandler.fuel_Left.cur_warn_level)
            elif tank_selection == 2:
                self.indicator_tank_select.setCurrentWarnLevel(warnhandler.Fuel_right.cur_warn_level)

            self.readout_left_fuel.setText("%5.1fL" % self.fuel_left_l)
            self.readout_right_fuel.setText("%5.1fL" % self.fuel_right_l)
            self.readout_air_temp.setText("%.1f℃" % temp_air_degree)
            self.readout_cyl2_temp.setText("%d℃" % temp_cyl2_degree)
            self.readout_cyl3_temp.setText("%d℃" % temp_cyl3_degree)
            self.readout_gas1_temp.setText("%d℃" % temp_gas1_degree)
            self.readout_gas2_temp.setText("%d℃" % temp_gas2_degree)
            self.readout_gas3_temp.setText("%d℃" % temp_gas3_degree)
            self.readout_gas4_temp.setText("%d℃" % temp_gas4_degree)
        except Exception as e:
            logging.error(e.args)  # 访问异常的错误编号和详细信息
            logging.error(str(e))
            logging.error(repr(e))

    def warnning_system_data_process(self, data):
        pass

    def command_echo_data_process(self, data):
        pass

    def equipment_data_process(self, data):
        pass
